import SwiftUI

// 遵循UIViewControllerRepresentable协议
struct SwiftUICallSwift: UIViewControllerRepresentable {
    var color : UIColor?
    func makeUIViewController(context: Context) -> some UIViewController {
        let vc = FCUIViewController()
        return vc
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        
    }
}

class FCUIView: UIView, UITextFieldDelegate{
    var m_paint = FCPaint()
    var m_isInit = false
    var m_textBox = UITextField()
    var m_editingTextBox = FCTextBox()
    var m_initTextBox : Bool = false
    
    /*
     * 显示文本框
     */
    func showTextBox(textBox:FCTextBox, lastView:FCView){
        if m_initTextBox{
            if lastView.isNotEmpty && lastView != textBox && lastView.viewType == "textbox"{
                lastView.text = m_textBox.text!
                invalidateView(view: lastView)
            }
        }
        m_editingTextBox = textBox
        let scaleFX = m_paint.scaleFactorX
        let scaleFY = m_paint.scaleFactorY
        let clx = clientX(view: textBox)
        let cly = clientY(view: textBox)
        let x = (clx * scaleFX) + 1
        let y = (cly * scaleFY) + 1
        let cx = (textBox.size.cx - 2) * scaleFX
        let cy = (textBox.size.cy - 2) * scaleFY
        let rect  = CGRect(x:x, y: y, width: cx, height: cy)
        if !m_initTextBox{
            m_textBox = UITextField()
            m_initTextBox = true
        }
        m_textBox.text = textBox.text
        m_textBox.backgroundColor = stringToColor(str: textBox.backColor)
        m_textBox.textColor = stringToColor(str: textBox.textColor)
        let strs = textBox.font.split(separator: ",")
        var fontName = String(strs[0])
        if fontName == "Default"{
            fontName = m_paint.systemFont
        }
        var fontSize = StringToFloat(str: String(strs[1]))
        fontSize = CGFloat(min(m_paint.scaleFactorX, m_paint.scaleFactorY)) * fontSize
        m_textBox.font = UIFont(name: fontName, size: fontSize)
        self.addSubview(m_textBox)
        m_textBox.becomeFirstResponder()
        m_textBox.frame = rect
        m_textBox.delegate = self
    }
    
    /*
     * 收起键盘
     */
    func textFieldShouldReturn(_ textField: UITextField)-> Bool
    {
        if m_editingTextBox.isNotEmpty{
            hideTextBox(textBox: m_editingTextBox)
        }
        //收起键盘
        textField.resignFirstResponder()
        return true
    }
    
    /*
     * 隐藏文本框
     */
    func hideTextBox(textBox:FCTextBox){
        m_editingTextBox.text = m_textBox.text!
        m_textBox.removeFromSuperview()
        invalidateView(view: textBox)
        m_editingTextBox = FCTextBox()
        m_editingTextBox.isNotEmpty = false
    }
    
    /*
     * 触摸开始事件
     * paint 绘图对象
     * firstTouch:是否第一次触摸
     * firstPoint:第一次触摸的坐标
     * secondTouch:是否第二次触摸
     * secondPoint:第二次触摸的坐标
     */
    func handleTouchDown(paint:FCPaint, firstTouch:Bool, firstPoint:FCPoint, secondTouch:Bool, secondPoint:FCPoint) {
        paint.cancelClick = false
        let mp = FCPoint(x:firstPoint.x, y:firstPoint.y)
        paint.touchDownPoint = FCPoint(x:mp.x, y:mp.y)
        paint.touchDownView = [FCView]()
        let lastFocusedView = paint.getFocusedView()
        let fView = findView(mp:mp, views:paint.views)
        let newClickTime = getTickCount()
        if newClickTime - paint.lastClickTime < 250{
            paint.isDoubleClick = true
            paint.lastClickTime = 0
        }else{
            paint.isDoubleClick = false
            paint.lastClickTime = newClickTime
        }
        if fView.isNotEmpty{
            paint.setTouchDownView(view:fView)
            checkShowMenu(paint:paint)
            paint.setFocusedView(view:paint.getTouchDownView())
            let clx = clientX(view:paint.getTouchDownView())
            let cly = clientY(view:paint.getTouchDownView())
            let firstPointCopy = FCPoint(x:firstPoint.x, y:firstPoint.y)
            firstPointCopy.x -= clx
            firstPointCopy.y -= cly
            if paint.hasTouchBeginEvent{
                paint.onTouchBegin(paint.getFocusedView(), firstTouch, firstPointCopy, secondTouch, secondPoint)
            }else{
                onTouchBeginDefault(view: paint.getFocusedView(), firstTouch: firstTouch, firstPoint: firstPointCopy, secondTouch: secondTouch, secondPoint: secondPoint)
            }
            if fView.viewType == "textbox"{
                showTextBox(textBox: fView as! FCTextBox, lastView: lastFocusedView)
            }else{
                if(m_editingTextBox.isNotEmpty){
                    hideTextBox(textBox: m_editingTextBox)
                }
            }
            if(fView.allowResize){
                fView.resizePoint = getResizeState(view:fView, mp:firstPointCopy)
                if fView.resizePoint != -1{
                    fView.startRect = FCRect(left:fView.location.x, top:fView.location.y, right:fView.location.x + fView.size.cx, bottom:fView.location.y + fView.size.cy)
                }
            }
        }
    }

    /*
     * 触摸移动事件
     * paint 绘图对象
     * firstTouch:是否第一次触摸
     * firstPoint:第一次触摸的坐标
     * secondTouch:是否第二次触摸
     * secondPoint:第二次触摸的坐标
     */
    func handleTouchMove(paint:FCPaint, firstTouch:Bool, firstPoint:FCPoint, secondTouch:Bool, secondPoint:FCPoint) {
        if paint.getTouchDownView().isNotEmpty {
            let mp = FCPoint(x:firstPoint.x, y:firstPoint.y)
            let mDownView = paint.getTouchDownView()
            let pParent = findPreviewsEventParent(view:paint.getFocusedView());
            if pParent.isNotEmpty && pParent.allowDragScroll && (pParent.viewType == "div" || pParent.viewType == "layout" || pParent.viewType == "menu") {
                paint.setTouchDownView(view: pParent)
                paint.setFocusedView(view: pParent)
                paint.setTouchMoveView(view: pParent)
                let clx = clientX(view:pParent)
                let cly = clientY(view:pParent)
                let cmp = FCPoint(x:mp.x, y:mp.y)
                cmp.x -= clx
                cmp.y -= cly
                touchDownDiv(div:pParent as! FCDiv, firstTouch:firstTouch, firstPoint:cmp, secondTouch:secondTouch, secondPoint:secondPoint, clicks: 1)
                touchMoveDiv(div:pParent as! FCDiv, firstTouch:firstTouch, firstPoint:cmp, secondTouch:secondTouch, secondPoint:secondPoint)
                invalidateView(view:pParent)
            }else{
                let clx = clientX(view:mDownView)
                let cly = clientY(view:mDownView)
                let cmp = FCPoint(x:mp.x, y:mp.y)
                cmp.x -= clx
                cmp.y -= cly
                if paint.hasTouchMoveEvent{
                    paint.onTouchMove(mDownView, firstTouch, cmp, secondTouch, secondPoint)
                }else{
                    onTouchMoveDefault(view: mDownView, firstTouch: firstTouch, firstPoint: cmp, secondTouch: secondTouch, secondPoint: secondPoint)
                }
                if mDownView.resizePoint != -1{
                    let newBounds = FCRect(left:mDownView.startRect.left, top:mDownView.startRect.top, right:mDownView.startRect.right, bottom:mDownView.startRect.bottom)
                    windowResize(rect:newBounds, resizePoint:mDownView.resizePoint, nowPoint:mp, startTouchPoint:paint.touchDownPoint)
                    mDownView.location = FCPoint(x:newBounds.left, y:newBounds.top)
                    mDownView.size = FCSize(cx:newBounds.right - newBounds.left, cy:newBounds.bottom - newBounds.top)
                    if mDownView.getParent().isNotEmpty {
                        invalidateView(view:mDownView.getParent())
                    } else {
                        invalidate(paint:paint)
                    }
                }
                else if mDownView.allowDrag {
                    if (abs(mp.x - paint.touchDownPoint.x) > 5 || abs(mp.y - paint.touchDownPoint.y) > 5) {
                        paint.dragBeginRect = FCRect(left:mDownView.location.x, top:mDownView.location.y,
                                                     right:mDownView.location.x + mDownView.size.cx,
                                                     bottom:mDownView.location.y + mDownView.size.cy)
                        paint.dragBeginPoint = FCPoint(x:paint.touchDownPoint.x, y:paint.touchDownPoint.y)
                        paint.setDraggingView(view:mDownView)
                        paint.touchDownView = [FCView]()
                    }
                }
            }
        }
        else if paint.getDraggingView().isNotEmpty {
            let mp = FCPoint(x:firstPoint.x, y:firstPoint.y)
            let offsetX = mp.x - paint.dragBeginPoint.x
            let offsetY = mp.y - paint.dragBeginPoint.y
            let newBounds = FCRect(left:paint.dragBeginRect.left + offsetX, top:paint.dragBeginRect.top + offsetY,
                                   right:paint.dragBeginRect.right + offsetX, bottom:paint.dragBeginRect.bottom + offsetY)
            let dView = paint.getDraggingView()
            dView.location = FCPoint(x:newBounds.left, y:newBounds.top)
            if (paint.getDraggingView().getParent().isNotEmpty && paint.getDraggingView().getParent().viewType == "split") {
                (paint.getDraggingView().getParent() as! FCSplitLayoutDiv).splitPercent = -1
                resetSplitLayoutDiv(split:paint.getDraggingView().getParent() as! FCSplitLayoutDiv);
                if (paint.hasUpdateViewEvent) {
                    paint.onUpdateView(paint.views);
                  } else {
                    updateViewDefault(views:paint.views);
                  }
            }
            if dView.getParent().isNotEmpty {
                invalidateView(view:dView.getParent())
            } else {
                invalidate(paint:paint)
            }
        }
    }

    /*
     * 触摸抬起事件
     * paint 绘图对象
     * firstTouch:是否第一次触摸
     * firstPoint:第一次触摸的坐标
     * secondTouch:是否第二次触摸
     * secondPoint:第二次触摸的坐标
     */
    func handleTouchUp(paint:FCPaint, firstTouch:Bool, firstPoint:FCPoint, secondTouch:Bool, secondPoint:FCPoint) {
        if paint.getTouchDownView().isNotEmpty {
            let mp = FCPoint(x:firstPoint.x, y:firstPoint.y)
            let mDownView = paint.getTouchDownView()
            let clx = clientX(view:mDownView)
            let cly = clientY(view:mDownView)
            var clicks = 1
            if paint.isDoubleClick {
                clicks = 2
            }
            let cmp = FCPoint(x:mp.x, y:mp.y)
            cmp.x -= clx
            cmp.y -= cly
            let view = findView(mp:mp, views:paint.views)
            if view.isNotEmpty && view == mDownView {
                if paint.hasClickEvent{
                    paint.onClick(view, true, cmp, false, cmp, 1)
                }else{
                    onClickDefault(view: view, firstTouch: true, firstPoint: cmp, secondTouch: false, secondPoint: cmp, clicks: clicks)
                }
            }
            mDownView.resizePoint = -1;
            if paint.hasTouchEndEvent{
                paint.onTouchEnd(mDownView, firstTouch, cmp, secondTouch, secondPoint)
            }else{
                onTouchEndDefault(view: mDownView, firstTouch: firstTouch, firstPoint: cmp, secondTouch: secondTouch, secondPoint: secondPoint)
            }
            paint.touchDownView = [FCView]()
        }
        paint.draggingView = [FCView]()
    }
    
    /*
     * 初始化布局
     */
    func onLoad(){
        if !self.m_isInit{
            m_editingTextBox.isNotEmpty = false
            self.isMultipleTouchEnabled = true
            self.m_isInit = true
            m_paint.setUIView(view: self)
            //renderFaceCat(paint: m_paint, size: FCSize(cx:width, cy:height))
            self.perform(#selector(self.onTimer), with: "", afterDelay: 0.01)
        }
    }
    
    @objc func onTimer(){
        updateScroll(views: m_paint.views)
        self.perform(#selector(self.onTimer), with: "", afterDelay: 0.01)
    }
    
    override func draw(_ rect: CGRect) {
        onLoad()
        if m_paint.size.cx != self.frame.size.width || m_paint.size.cy != self.frame.size.height{
            m_paint.size = FCSize(cx:self.frame.size.width, cy:self.frame.size.height);
            if(self.m_paint.hasUpdateViewEvent){
                self.m_paint.onUpdateView(self.m_paint.views)
            }else{
                updateViewDefault(views: self.m_paint.views)
            }
        }
        let cRect = CGRect(x: rect.origin.x, y: rect.origin.y, width: rect.width, height: rect.height)
        let drawRect = FCRect(left: cRect.origin.x / m_paint.scaleFactorX, top: cRect.origin.y / m_paint.scaleFactorY, right: (cRect.origin.x + cRect.width) / m_paint.scaleFactorX, bottom:(cRect.origin.y + cRect.height) / m_paint.scaleFactorY)
        m_paint.beginPaint(rect: drawRect)
        renderViews(views: self.m_paint.views, paint: self.m_paint, rect: drawRect)
        m_paint.endPaint()
    }
    
    var firstTouchCache = false
    var secondTouchCache = false
    var firstPointCache = FCPoint(x:0, y:0)
    var secondPointCache = FCPoint(x:0, y:0)
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        firstTouchCache = false
        secondTouchCache = false
        firstPointCache = FCPoint(x:0, y:0)
        secondPointCache = FCPoint(x:0, y:0)
        var i = 0
        for touch:AnyObject in touches {
            let t:UITouch = touch as! UITouch
            let point = t.location(in: self)
            if i == 0{
                firstTouchCache = true
                firstPointCache = FCPoint(x:Double(point.x), y:Double(point.y))
                firstPointCache.x /= m_paint.scaleFactorX
                firstPointCache.y /= m_paint.scaleFactorY
            }else if i == 1{
                secondTouchCache = true
                secondPointCache = FCPoint(x:Double(point.x), y:Double(point.y))
                secondPointCache.x /= m_paint.scaleFactorX
                secondPointCache.y /= m_paint.scaleFactorY
            }
            i += 1
        }
        handleTouchDown(paint: m_paint, firstTouch: firstTouchCache, firstPoint: firstPointCache, secondTouch: secondTouchCache, secondPoint: secondPointCache)
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        var i = 0
        for touch:AnyObject in touches {
            let t:UITouch = touch as! UITouch
            let point = t.location(in: self)
            if i == 0{
                firstTouchCache = true
                firstPointCache = FCPoint(x:Double(point.x), y:Double(point.y))
                firstPointCache.x /= m_paint.scaleFactorX
                firstPointCache.y /= m_paint.scaleFactorY
            }else if i == 1{
                secondTouchCache = true
                secondPointCache = FCPoint(x:Double(point.x), y:Double(point.y))
                secondPointCache.x /= m_paint.scaleFactorX
                secondPointCache.y /= m_paint.scaleFactorY
            }
            i += 1
        }
        if firstTouchCache && secondTouchCache && i == 1{
            return
        }
        handleTouchMove(paint: m_paint, firstTouch: firstTouchCache, firstPoint: firstPointCache, secondTouch: secondTouchCache, secondPoint: secondPointCache)
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        var i = 0
        for touch:AnyObject in touches {
            let t:UITouch = touch as! UITouch
            let point = t.location(in: self)
            if i == 0{
                firstTouchCache = true
                firstPointCache = FCPoint(x:Double(point.x), y:Double(point.y))
                firstPointCache.x /= m_paint.scaleFactorX
                firstPointCache.y /= m_paint.scaleFactorY
            }else if i == 1{
                secondTouchCache = true
                secondPointCache = FCPoint(x:Double(point.x), y:Double(point.y))
                secondPointCache.x /= m_paint.scaleFactorX
                secondPointCache.y /= m_paint.scaleFactorY
            }
            i += 1
        }
        handleTouchUp(paint: m_paint, firstTouch: firstTouchCache, firstPoint: firstPointCache, secondTouch: secondTouchCache, secondPoint: secondPointCache)
    }
}
